﻿using XAMSDK.Types;

namespace XAMSDK
{
    /// <summary>Wrapper object for the XAM SDK library object</summary>
    /// <remarks>
    ///    Singleton class as only one reference to the XAM Library should ever be loaded.
    ///    <list>
    ///       <item>This class is the Factory method for creating connections
    ///           to XAM storage devices.</item>
    ///       <item>Fields related to XSystem options that are created on the instance
    ///           will be inherited by any XSystem connections created by it.</item>
    ///    </list>
    /// </remarks>

    public class XAMLibrary : XAMObject
    {
        #region Static Members

        static private XAMLibrary xamLibrary;
        static private bool initialised = false;

        #endregion

        #region Constructors
        /// <summary>
        /// Private constructor which obtains the XAMLibraryHandle
        /// </summary>
        /// <returns>A XAMLibrary instance</returns>
        private XAMLibrary()
        {
            xamHandle = Constants.XAM_LIBRARY_HANDLE;
            initialised = true;
        }

        #endregion

        #region Static Property
        /// <summary>
        /// Returns the instance of the XAMLibrary object or creates it if not already initialised
        /// </summary>
        /// <returns>The XAMLibrary instance</returns>
        static public XAMLibrary Instance
        {
            get
            {
                if (!initialised)
                    xamLibrary = new XAMLibrary();

                return xamLibrary;
            }
        }
        #endregion

        #region Methods

        /// <summary>
        /// Factory method for creation XSystem instances
        /// </summary>
        /// <param name="connectionString">consists of (optional) VIM name, (mandatory) address of the XAM storage
        ///         platform and (optional) additional device specific parameters.
        ///         e.g. ""snia-xam://centera_vim!128.221.200.60?xam.pea""</param>
        /// <returns>An XSystem instance</returns>
        public XSystem CreateXSystem(string connectionString)
        {
            XSystemHandle xsysh;
            int retval = Imports.XAMLibrary_Connect(connectionString, out xsysh);
            Helpers.CheckAndThrow(retval, "XAMLibrary_Connect");

            XSystem xsys = new XSystem(xsysh);

            // Note: In this case, we don't need to add the created XSystem to the factoryObjects collection.
            // The XAMLibrary is a singleton, and does not have a "close" method where this list is used.
            // It is not subject to the issues where child objects that have not been closed can cause
            // issues if not properly tidied up.

            return xsys;
        }
        #endregion

        #region Read Only Properties
        /// <summary>
        /// The origin of the XAM Library (e.g. org.snia). It is intended for informational
        /// use; applications should not code specific behavior with respect to this value.
        /// </summary>
        /// <returns>The value of the .xam.identity string field.</returns>
        public XString Identity { get { XString value = new XString(); GetField(Constants.IDENTITY, value); return value; } }

        /// <summary>
        /// The version of the XAM API that is implemented (e.g. 1.0.0).
        /// </summary>
        /// <returns>The value of the .xam.apiLevel string field.</returns>
        public XString APILevel { get { XString value = new XString(); GetField(Constants.API_LEVEL, value); return value; } }
        #endregion

        #region Properties
        /// <summary>
        /// The current level of library logging. This controls what type of information
        /// is logged. Applications may set this value to control the log.
        /// </summary>
        /// <returns>The value of the .xam.log.level field.</returns>
        public long LogLevel 
        { 
            get { long value = 0; GetField(Constants.LOG_LEVEL, out value); return value; }
            set { SetField(Constants.LOG_LEVEL, value); }
        }

        /// <summary>
        /// The verbosity level of logging; the higher the value, the more detail is logged. Applications may set this
        /// value to control the log.
        /// </summary>
        /// <returns>The value of the .xam.log.verbosity field.</returns>
        public long LogVerbosity
        {
            get
            {
                long value = 0;
                GetField(Constants.LOG_VERBOSITY, out value);
                return value;
            }
            set
            {
                SetField(Constants.LOG_VERBOSITY, value);
            }
        }
        /// <summary>
        /// The path of the file to write the log into.
        /// </summary>
        /// <returns>The value of the .xam.log.path field.</returns>
        public XString LogPath 
        {
            get { XString value = new XString(); GetField(Constants.LOG_PATH, value); return value; }
            set { SetField(Constants.LOG_PATH, value); }
        }
        #endregion
    }

}